#!/usr/bin/env python
# -*- coding: utf-8 -*-

__copyright__ = 'Copyright 2005, Janrain, Inc. and AmSoft 2006'

from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
from urlparse import urlparse
from urlparse import urlsplit

import time
import Cookie
import cgi
import cgitb
import sys
import MySQLdb

# Service Layer Class
from issoservice import IssoService

# Iservices-specific Exception classes
from exception import IservicesSysException

# Required to read properties file
from properties import Properties
import inspect

# Required for logging
import logging
from logutil import LogUtil
from errcode import *

# Required to resolve iname
import urllib
from xml.dom import minidom

from Cheetah.Template import Template

#Page template classes
from password import password
from trustpref import trustpref
from retry import retry
from error import error

def quoteattr(s):
    qs = cgi.escape(s, 1)
    return '"%s"' % (qs,)

try:
    import openid
except ImportError:
    print >>sys.stderr, """
Failed to import the OpenID library. In order to use this example, you
must either install the library (see INSTALL in the root of the
distribution) or else add the library to python's import path (the
PYTHONPATH environment variable).

For more information, see the README in the root of the library
distribution or http://www.openidenabled.com/
"""
    sys.exit(1)

from openid import oidutil
from openid.server import server
from openid.store.filestore import FileOpenIDStore
from openid.store.sqlstore import MySQLStore

# Handle to Resource Bundle
oBundleProp = Properties()
    
class OpenIDHTTPServer(HTTPServer):
    """
    http server that contains a reference to an OpenID Server and
    knows its base URL.
    """
    def __init__(self, oidserver, *args, **kwargs):
        HTTPServer.__init__(self, *args, **kwargs)

        if self.server_port != 80:
            self.base_url = ('http://%s:%s/' %
                             (self.server_name, self.server_port))
        else:
            self.base_url = 'http://%s/' % (self.server_name,)

        self.openid = oidserver
        self.approved = {}
        self.lastCheckIDRequest = {}

class ServerHandler(BaseHTTPRequestHandler):    
    def __init__(self, *args, **kwargs):
        self.user = None
        BaseHTTPRequestHandler.__init__(self, *args, **kwargs)

    def do_GET(self):
        """
        This function handles all GET requests.
        """
        LogUtil.log(logging.DEBUG, 'do_GET(): Entry')
        try:
            self.parsed_uri = urlparse(self.path)
            self.query = {}
            for k, v in cgi.parse_qsl(self.parsed_uri[4]):
                self.query[k] = v

            self.setUser()
            
            path = self.parsed_uri[2].lower()

            if path == '/' or path == '/openidserver/':
                self.serverEndPoint(self.query)
            else:
                self.send_response(404)
                self.end_headers()

        except (KeyboardInterrupt, SystemExit):
            raise
        except:
            self.send_response(500)
            self.send_header('Content-type', 'text/html')
            self.end_headers()
            self.wfile.write(cgitb.html(sys.exc_info(), context=10))

    def do_POST(self):
        """
        This function handles all POST requests.
        """
        LogUtil.log(logging.DEBUG, 'do_POST(): Entry')
        # Get DB connection parameters from properties file
        sPath = 'db.properties'    
        oProp = Properties()
        oProp.load(open(sPath))
    
        conn = MySQLdb.connect (host = oProp['host'],
                               user = oProp['user_name'],
                               passwd = oProp['password'],
                               db = oProp['database'])
    
        store = MySQLStore(conn)
        oidserver = server.OpenIDServer(store)

        try:
            self.parsed_uri = urlparse(self.path)

            self.setUser()
            content_length = int(self.headers['Content-Length'])
            post_data = self.rfile.read(content_length)

            self.query = {}
            for k, v in cgi.parse_qsl(post_data):
                self.query[k] = v

            LogUtil.log(logging.DEBUG, 'do_POST(): query=' + str(self.query))
            request = oidserver.decodeRequest(self.query)
            LogUtil.log(logging.DEBUG, 'do_POST(): request=' + str(request))
            
            if request <> None:
                LogUtil.log(logging.DEBUG,
                            'do_POST(): mode=' + str(request.mode))
                if request.mode not in ["checkid_immediate", "checkid_setup"]:
                    response = oidserver.handleRequest(request)
                    LogUtil.log(logging.DEBUG,
                                'do_POST(): response=' + str(response))
                    self.displayResponse(response)
                    self.send_response(200)
                    self.end_headers()
                    return

            path = self.parsed_uri[2]
            if path == '/' or path == '/openidserver/':
                self.serverEndPoint(self.query)
            elif path == '/openidserver/verifyuser':
                self.verifyUser(self.query)
            elif path == '/openidserver/verifytrust':
                self.verifyTrust(self.query)
            elif path == '/openidserver/logout':
                self.logout(self.query)
            else:
                self.send_response(404)
                self.end_headers()

        except (KeyboardInterrupt, SystemExit):
            raise
        except:
            self.send_response(500)
            self.send_header('Content-type', 'text/html')
            self.end_headers()
            self.wfile.write(cgitb.html(sys.exc_info(), context=10))

    def displayResponse(self, response):
        
        try:
            webresponse = self.server.openid.encodeResponse(response)
        except server.EncodingError, why:
            text = why.response.encodeToKVForm()
            #self.showErrorPage('<pre>%s</pre>' % cgi.escape(text))
            self.showIServicesErrorPage(cgi.escape(text))
            return
        LogUtil.log(logging.DEBUG, 'displayResponse(): ' +
                    'response=' + str(response))
        
        LogUtil.log(logging.DEBUG, 'displayResponse(): ' +
                    'webresponse=' + str(webresponse))
        
        self.send_response(webresponse.code)
        for header, value in webresponse.headers.iteritems():
            self.send_header(header, value)
            LogUtil.log(logging.DEBUG, 'displayResponse(): ' +
                    'header=' + str(header) + ", value=" + value)
            
        
        self.writeUserHeader()
        self.end_headers()

        if webresponse.body:
            self.wfile.write(webresponse.body)

    def getCookie(self, cookie_name):
        """
        This function returns value of the Cookie with specified name.
        """
        cookies = self.headers.get('Cookie')
        if cookies:
            morsel = Cookie.BaseCookie(cookies).get(cookie_name)
            if morsel:
                return morsel.value
            else:
                return None
        else:
            return None

    def getHeaderInfo(self, data_name):
        """
        This function returns header value for the specified parameter.
        """
        value = self.headers.get(data_name)
        LogUtil.log(logging.DEBUG, 'getHeaderInfo(): ' +
                    data_name + '=' + value)
        if value:
            return value
        else:
            return None

    def getIBrokerData(self, sIBrokerName):
        """
        This function fetches IBroker data and formats for UI.
        """
        try:
            oIBroker = IssoService.getIBrokerData(sIBrokerName)
        except IservicesSysException:
            oEx = sys.exc_info()[1]
            if oEx.getCode() == 2028:
                LogUtil.log(logging.DEBUG,
                            'getIBrokerData(): IservicesSysException='+str(oEx))
                oIBroker = None
            elif oEx.getCode() == 2004:
                LogUtil.log(logging.DEBUG,
                            'getIBrokerData(): IservicesSysException='+str(oEx))
                oIBroker = None
        except:
            oEx = sys.exc_info()[1]
            LogUtil.log(logging.DEBUG,
                        'getIBrokerData(): Exception='+str(oEx))
            oIBroker = None
        
        if oIBroker != None:
            # Get IBroker Data
            oData = oIBroker.getData()

            # Convert into an array
            length = len(oData)
            aData = []
            if 'ad-banner' in oData:
                aData.append(oData['ad-banner'])
            else:
                aData.append('images')
    
            i = 1
            limit = length/2
            while i <= limit:
                sLinkName = 'link' + str(i) + '_text'
                sLinkAddress = 'link' + str(i) + '_url'
                aData.append(oData[sLinkName])
                aData.append(oData[sLinkAddress])
                i = i + 1
            
            # Return data array
            LogUtil.log(logging.DEBUG,
                        'getIBrokerData(): Returning List=' + str(aData))
            return aData
        else:
            aData = ['images']
            LogUtil.log(logging.DEBUG,
                        'getIBrokerData(): Returning List=' + str(aData))
            return aData
    
    def getProperty(self, sKeyName):
        """
        This function reads labels and messages from properties file while
        taking care of internationalization as well.
        """
        sValue = oBundleProp[sKeyName]
        decstr = sValue.decode('unicode_escape')
        return decstr

    def getStaticLinks(self, aData, url):
        """
        This function returns links to be displayed on the left side of page.
        """
        sLinks = ''
        num = 1
        if not aData == None:
            # Create links
            i = 1
            num = len(aData)-1
            for i in range(1, num, 2):
                linkData = {
                    'td': 'td' + str(i), 
                    'left-menu-middle': url + 'images/default/left-menu-middle.gif',
                    'left-menu-middle-grey': url + 'images/default/left-menu-middle-grey.gif', 
                    'name': aData[i],
                    'address': aData[i+1]
                }
                sNewLink = '''\
                    <tr>
                        <td id="%(td)s" class="white-smalltext" background="%(left-menu-middle)s" height="32"
                        onmouseover=this.style.backgroundImage="url('%(left-menu-middle-grey)s')"
                        onmouseout=this.style.backgroundImage="url('%(left-menu-middle)s')">
                                &nbsp;&nbsp;
                                <a class="link-nounderline white-smalltext" href="%(address)s">%(name)s</a>
                        </td>
                    </tr>
                ''' % linkData
                sLinks = sLinks + sNewLink
            
        # Create empty links
        num = num/2
        for num in range(num,8):
            linkData = {
                'td': 'td' + str(num+1), 
                'left-menu-middle-blank': url + 'images/default/left-menu-middle-blank.gif'
            }
            sNewLink = '''\
                <tr><td id="%(td)s" background="%(left-menu-middle-blank)s" height="32"></td></tr>
            ''' % linkData
            sLinks = sLinks + sNewLink
            num = num + 1
        
        # Return links display data
        return sLinks
    
    def getXRIProperty(self, sKey):
        """
        # TODO: Load xriclient resource bundle file
        sPath = inspect.getfile(sys._getframe(1))
        iLen = sPath.index ('\iservice') + 9
        sPath = sPath[0:iLen]
        sPath = sPath + '\util\\xriclient.properties'        
        pXRI = Properties()
        LogUtil.log(logging.WARN, 'getXRIProperty(): Loading file=' + sPath)
        pXRI.load(open(sPath))
        """
        p = Properties()
        p.load(open('resources.properties'))
        sPath = p['xripath']
        pXRI = Properties()
        LogUtil.log(logging.WARN, 'getXRIProperty(): Loading file=' + sPath)
        pXRI.load(open(sPath))
        
        # Return Value for given Key
        return pXRI[sKey]

    def loadResourceBundle(self, sLocale):
        """
        This function loads Resource Bundle for a request.
        """
        """
        # TODO: Get absolute file path for properties file
        sPath = inspect.getfile(sys._getframe(1))
        iLen = sPath.index ('\isso') + 5
        sPath = sPath[0:iLen]
        sPath = sPath + '\webapp\conf\issoResources'
        sFilePath = sPath + '_' + sLocale + '.properties'
            
        # Check if properties file for this locale exists or not
        import os
        if not os.path.exists(sFilePath):
            LogUtil.log(logging.DEBUG, 'loadResourceBundle(): No resource ' +
                        'could be found for locale \'' + sLocale + '\'.' +
                        'Loading default resource bundle')
            sFilePath = sPath + '.properties'
        """        
        p = Properties()
        p.load(open('resources.properties'))
        sFilePath = p['base'] + '_' + sLocale + p['ext']

        # Check if properties file for this locale exists or not
        import os
        if not os.path.exists(sFilePath):
            LogUtil.log(logging.DEBUG, 'loadResourceBundle(): No resource ' +
                        'could be found for locale \'' + sLocale + '\'.' +
                        'Loading default resource bundle')
            sFilePath = p['base'] + p['ext']
        
        LogUtil.log(logging.DEBUG,
                    'loadResourceBundle(): Loaded file=' + sFilePath)
        
        oBundleProp.load(open(sFilePath))
    
    def getIserviceProperty(self, sKey):
        """
        Load Iservice Util resource bundle file
        """
        p = Properties()
        p.load(open('resources.properties'))
        sPath = p['iserviceutil']
        pIservice = Properties()
        LogUtil.log(logging.INFO, 'getIserviceProperty(): Loading file=' + sPath)
        pIservice.load(open(sPath))
        
        # Return Value for given Key
        return pIservice[sKey]
    
    def logout(self, query):
        """
        This function is called when user clicks 'Logout' button on 'Decide
        Page'. It expires the session cookie corresponding to the user and
        redirects the user to 'IdP Login Page'.
        """
        # Set user=None
        self.user = None
        
        # Get Session Cookie
        locale = query['locale']
        cookie_name = self.getProperty('session.cookie.name')
        cookie_value = self.getCookie(cookie_name)
        LogUtil.log(logging.DEBUG,
                    'logout(): Session Cookie=' + str(cookie_value))
        
        # Expire cookie in DB
        IssoService.logout(cookie_value)
        
        # Redirect to ISSO Login Page
        self.send_response(302)
        url = 'https://' + query['broker'] + '/isso/'
        self.send_header('Location', url)
        url = 'http://' + query['broker'] + '/isso/'
        LogUtil.log(logging.DEBUG, 'logout(): Redirecting to URL=' + url)

        # Expire cookie in browser
        self.writeCookiesHeader(cookie_name, cookie_value, 0)
        self.end_headers()
        return

    def redirect(self, url):
        self.send_response(302)
        self.send_header('Location', url)
        self.writeUserHeader()

        self.end_headers()

    def resolveIname(self, sIname):
        """
        This function resolves an i-name and returns corresponding global
        i-number.
        """
        LogUtil.log(logging.DEBUG, 'resolveIname(): iname=' + sIname)
        # Check if an i-name is provided or not
        if sIname == None or sIname == '':
            LogUtil.log(logging.ERROR, 'resolveIname(): IservicesSysException='
                        + str(dUtilErrorCodeMap[INSUFFICENT_DATA]))
            # Throw exception: Insufficient Data
            raise IservicesSysException(INSUFFICENT_DATA,
                                        dUtilErrorCodeMap[INSUFFICENT_DATA])
        
        # Get relevant Proxy URL
        sProxyURL = '%s'
        if (sIname[0] == '='):
            sProxyURL = self.getXRIProperty('proxy.uri.equal') + '/%s'
        elif (sIname[0] == '@'):
            sProxyURL = self.getXRIProperty('at.uri.equal') + '/%s'
        else:
            LogUtil.log(logging.ERROR, 'resolveIname(): IservicesSysException='
                        + str(dUtilErrorCodeMap[INAME_INVALID]))
            # Throw exception: Iname is not valid
            raise IservicesSysException(INAME_INVALID,
                                        dUtilErrorCodeMap[INAME_INVALID])
        
        # Create qxri to be queried
        if (sIname[0] == '=' or sIname[0] == '@' or sIname[0] == '!'):
            if (sIname[1] == '!' or sIname[1] == '*'):
                sIname = sIname[1:]
            else:
                sIname = "*" + sIname[1:]
        else:
            LogUtil.log(logging.ERROR, 'resolveIname(): IservicesSysException='
                        + str(dUtilErrorCodeMap[INAME_INVALID]))
            # Throw exception: Iname is not valid
            raise IservicesSysException(INAME_INVALID,
                                        dUtilErrorCodeMap[INAME_INVALID])
        
        # Append qxri to proxy server url
        sUrl = sProxyURL %(sIname)
        oXrds = None
        
        # Fetch XRDS for the i-name
        try:
            LogUtil.log(logging.WARN, 'resolveIname(): Fetching XRDS for URL='
                        + str(sUrl))
            oXrds = minidom.parse(urllib.urlopen(sUrl))
        except:
            LogUtil.log(logging.ERROR, 'resolveIname(): IservicesSysException='
                        + str(dUtilErrorCodeMap[INAME_NOT_RESOLVED]))
            # Throw exception: Iname/Inumber can't be resolved
            raise IservicesSysException(INAME_NOT_RESOLVED,
                                        dUtilErrorCodeMap[INAME_NOT_RESOLVED])
        
        oElement =  oXrds.getElementsByTagName('CanonicalID')
        sGinu = oElement[0].firstChild.data
	sGinu = sGinu.lower()
        LogUtil.log(logging.DEBUG, 'resolveIname(): Returning ginu=' + sGinu)
        return sGinu

    def serverEndPoint(self, query):
        """
        This function handles all the requests sent to the openidserver.
        """
        try:
            LogUtil.log(logging.DEBUG, 'serverEndPoint(): Entry with query=' +
                        str(query))
			if (('openid.assoc_handle' not in query) or ('openid.identity' not in query) or('openid.mode' not in query) or('openid.return_to' not in query) or('openid.trust_root' not in query)):
                LogUtil.log(logging.DEBUG,"serverEndPoint(): query parameters not complete")
                self.showIServicesErrorPage(query,"Page can not be Displayed")
                return
				
            request = self.server.openid.decodeRequest(query)
            LogUtil.log(logging.DEBUG, 'serverEndPoint(): Decoded query, ' + 
                        'request= ' + str(request))
        except server.ProtocolError, why:
            LogUtil.log(logging.ERROR, 'serverEndPoint(): Query not decoded, '+
                        'Exception= ' + str(why))
            self.displayResponse(why)
            return

        if request is None:
            return
        
        self.user = self.getIname(request.identity)
        LogUtil.log(logging.DEBUG, 'serverEndPoint(): user=' + str(self.user))
        if self.server.lastCheckIDRequest.get(self.user) == None:
            self.server.lastCheckIDRequest[self.user] = request
        
        # Get Locale from Request
        locale = self.getHeaderInfo('Accept-Language')
        locale = locale[:2]
        LogUtil.log(logging.DEBUG, 'serverEndPoint(): locale=' + locale)
        
        # Load Resource Bundle
        self.loadResourceBundle(locale)

        #Handle Dumb mode
        if request.mode == "checkid_immediate":
            self.handleImmediateMode(query)
            return
        
        if request.mode in ["checkid_immediate", "checkid_setup"]:
            # Resolve i-name to get global i-number
            ginu = ''
            try:
                sIdentity = self.getIname(str(request.identity))
                
                LogUtil.log(logging.INFO,
                            'serverEndPoint(): Calling resolveIname() ' +
                            'user=' + sIdentity)
                ginu = self.resolveIname(sIdentity)
                LogUtil.log(logging.DEBUG,
                            'serverEndPoint(): Got ginu=' + ginu)
            except IservicesSysException:
                oEx = sys.exc_info()[1]
                sLogMessage = 'serverEndPoint(): IservicesSysException='
                if oEx.getCode() == 2028:
                    LogUtil.log(logging.ERROR,
                                sLogMessage + 'Insufficient data')
                    # Show Error Page
                    self.showIServicesErrorPage(query, 'Insufficient data')
                    return
                elif oEx.getCode() == 2040:
                    LogUtil.log(logging.ERROR,
                                sLogMessage + 'Invalid Iname')
                    # Show Error Page
                    self.showIServicesErrorPage(query, 'Invalid Iname')
                    return
                elif oEx.getCode() == 2034:
                    LogUtil.log(logging.ERROR,
                                sLogMessage +
                                'Iname/Inumber cannot be resolved')
                    # Show Error Page
                    self.showIServicesErrorPage(
                        query, 'Iname/Inumber cannot be resolved')
                    return
            except:
                oEx = sys.exc_info()[1]
                LogUtil.log(logging.ERROR,
                            'serverEndPoint(): Exception=' + str(oEx))
                # Show Error Page
                self.showIServicesErrorPage(query, oEx)
                return

            # Get IBroker name from Request
            host = urllib.splitport(self.getHeaderInfo('Host'))
            broker = str(host[0])
            LogUtil.log(logging.DEBUG, 'serverEndPoint(): host=' + str(host) +
                        ' broker=' + str(broker))

            password = None
            rememberMachine = True
            
            # Set Machine Cookie
            mcookie_name = self.getProperty('machine.cookie.name')
            mcookie = self.getCookie(mcookie_name)
            LogUtil.log(logging.DEBUG,
                        'serverEndPoint(): Machine Cookie=' + str(mcookie))

            # Set Session Cookie
            scookie_name = self.getProperty('session.cookie.name')
            scookie = self.getCookie(scookie_name)
            LogUtil.log(logging.DEBUG,
                        'serverEndPoint(): Session Cookie=' + str(scookie))

            # Check query parameters
            if 'password' in query:
                password = query['password']
            
            if 'rememberMachine' in query:
                if query['rememberMachine'] == 'false':
                    rememberMachine = False
            
            query['ginu'] = ginu
            query['broker'] = broker
            query['scookie'] = scookie
            query['mcookie'] = mcookie
            query['locale'] = locale
            query['rememberMachine'] = rememberMachine
            
            # Check if user is logged in
            if self.user:
                self.server.lastCheckIDRequest[self.user] = request

            bResult = "Failure"
            try:
                if password == None:
                    LogUtil.log(logging.WARN,
                                'serverEndPoint(): Calling login(), pwd=None')
                    bResult = IssoService.login(ginu, broker, scookie, mcookie)
                else:
                    LogUtil.log(logging.WARN,
                                'serverEndPoint(): Calling login() with pwd')
                    bResult = IssoService.login(ginu, broker, scookie, mcookie,
                                                password, rememberMachine)
            except Exception:
                oEx = sys.exc_info()[1]
                LogUtil.log(logging.ERROR,
                            'serverEndPoint(): Exception=' + str(oEx))
                bResult = "Failure"

            LogUtil.log(logging.DEBUG,
                        'serverEndPoint(): Login Result=' + str(bResult))

            if bResult == "Success":
                # Show Decide Page
                req = self.server.lastCheckIDRequest.get(self.user)
                if req == None or req == '':
                    self.server.lastCheckIDRequest[self.user] = request
                self.showIServicesDecidePage(query, request, rememberMachine)
                return
            elif bResult == "Password":
                # Show Password Page
                self.showIServicesPasswordPage(query, "You are not logged in.")
                return
            elif bResult == "Retry":
                # Show Retry Page
                self.showIServicesRetryPage(query)
                return
            else:
                # Show Retry Page
                #self.showIServicesRetryPage(query)
                #return
				self.showIServicesErrorPage(query,"i-name can not be resolved")
                return
        else:
            response = self.server.openid.handleRequest(request)
        self.displayResponse(response)

    def setUser(self):
        """
        This function sets user for the current request.
        """
        cookies = self.headers.get('Cookie')
        if cookies:
            morsel = Cookie.BaseCookie(cookies).get('user')
            if morsel:
                self.user = morsel.value

    def showIServicesDecidePage(self, query, request, rememberMachine):
        """
        This function displays 'Trust Preferences Page' to user. User can choose
        whether he wants to trust the consumer or not.
        """
        
        broker = query['broker']
        url = "http://" + broker + "/isso/"
        banner = url + 'images/' + broker + '/ad-banner.gif'
        sLinks = ''

        sTitle = self.getProperty('title.trustPreferences')
        msg = self.getProperty('label.trustMessage')
        allow_msg = self.getProperty('label.allowMessage')
        allow_str = self.getProperty('label.option.allow')
        deny_str = self.getProperty('label.option.deny')
        
        """
        sTitle = 'Trust Preferences'
        msg = '''\
        A new site has asked for your identity.  If you
        approve, the site represented by the trust root
        below will be told that you control identity URL
        listed below.'''
        allow_msg = 'Allow this authentication to proceed?'
        allow_str = 'Allow'
        deny_str = 'Deny'
        """
        
        # Prepare data for display
        aData = self.getIBrokerData(broker)
        
        # Get ad-banner
        if not aData == None:
            if not aData[0].startswith('images'):
                banner = aData[0]
        
        # Get static links
        sLinks = self.getStaticLinks(aData, url)
        
        contents = {
            'title': sTitle, 
            'stylesheet': url + 'styleSheets/iservices.css',
            'logo': url + 'images/' + broker + '/ibroker-logo.gif',
            'banner': banner,
            'left_menu_top': url + 'images/default/left-menu-top.gif', 
            'left_menu_middle': url + 'images/default/left-menu-middle.gif', 
            'left_menu_middle_blank': url + 'images/default/left-menu-middle-blank.gif', 
            'left_menu_bottom': url + 'images/default/left-menu-bottom.gif', 
            'tab_click_isso': url + 'images/default/tab-click-isso.jpg', 
            'tab_noclick_contact': url + 'images/default/tab-noclick-contact.jpg', 
            'tab_noclick_forwarding': url + 'images/default/tab-noclick-forwarding.jpg',
            'grey_square': url + 'images/default/grey-square.gif', 
            'title_isso_home': url + 'images/default/title_isso_home.gif', 
            'dotted_line': url + 'images/default/dotted-line.gif', 
            'button_submit': url + 'images/default/button-submit.jpg', 
            'button_logout': url + 'images/default/button-logout.jpg',
            'openid_identity': self.getIname(query['openid.identity']), 
            'openid_return_to': query['openid.return_to'], 
            'openid_mode': query['openid.mode'], 
            'openid_trust_root': query['openid.trust_root'], 
            'openid_assoc_handle': query['openid.assoc_handle'],
            'success_to': query['openid.return_to'], 
            'fail_to': query['openid.return_to'], 
            'ginu': query['ginu'],
            'broker': query['broker'],
            'scookie': query['scookie'],
            'mcookie': query['mcookie'],
            'locale': query['locale'],
            'white_square': url + 'images/default/white-square.gif', 
            'related_news': url + 'images/' + broker + '/related-news.gif',
            'message': msg,
            'allow_msg': allow_msg,
            'allow_str': allow_str,
            'deny_str': deny_str,
            'links': sLinks,
            'request': request
            }
        self.send_response(200)
        self.writeUserHeader()

        # Get Locale from Request
        locale = self.getHeaderInfo('Accept-Language')
        locale = locale[:2]

        # Set Session Cookie
        scookie_name = self.getProperty('session.cookie.name')
        scookie = ''
        if 'scookie' in query:
            scookie = query['scookie']
        
        if scookie == None or scookie == '':
            scookie = self.getCookie(scookie_name)

        expirytime = int(self.getProperty('session.server.validity.hours'))
        expirytime = expirytime * 60 * 60
        self.writeCookiesHeader(scookie_name, scookie, expirytime)
        LogUtil.log(logging.INFO,
                    'showIServicesDecidePage(): Written Session Cookie Header,'+
                    'name=' + scookie_name + ' value=' + str(scookie) +
                    'expiry=' + str(expirytime))

        # Check if user chose to delete machine cookie
        mcookie_name = self.getProperty('machine.cookie.name')
        mcookie_value = self.getCookie(mcookie_name)
        if not rememberMachine:
            expirytime = 0
        else:
            # Set Machine Cookie Header
            expirytime = int(self.getProperty('machine.server.validity.days'))
            expirytime = expirytime * 24 * 60 * 60
        self.writeCookiesHeader(mcookie_name, mcookie_value, expirytime)
        LogUtil.log(logging.INFO,
                    'showIServicesDecidePage(): Written Machine Cookie Header,'+
                    'name=' + mcookie_name + ' value=' + str(mcookie_value) +
                    'expiry=' + str(expirytime))
    
        self.writeContentTypeHeader()
        self.end_headers()
        
        #Create page HTML using tenplate
        oTemplate = trustpref(searchList = [contents])
        LogUtil.log(logging.DEBUG, 'showIServicesDecidePage(): Trust Pref. page ' 
                     + 'template created')
        page = str(oTemplate)
        #self.wfile.write(page.encode('utf-8'))
        self.wfile.write(page)

    def showIServicesErrorPage(self, query, msg):
        """
        This function displays 'Error Page' to user.
        """
        
        host = urllib.splitport(self.getHeaderInfo('Host'))
        broker = str(host[0])
        url = "http://" + broker + "/isso/"
        banner = url + 'images/' + broker + '/ad-banner.gif'
        sLinks = ''
        sTitle = 'I-SSO Error'
        
        # Prepare data for display
        aData = self.getIBrokerData(broker)
        
        # Get ad-banner
        if not aData == None:
            if not aData[0].startswith('images'):
                banner = aData[0]
        
        # Get static links
        sLinks = self.getStaticLinks(aData, url)
        
        contents = {
            'title': sTitle, 
            'stylesheet': url + 'styleSheets/iservices.css',
            'logo': url + 'images/' + broker + '/ibroker-logo.gif',
            'banner': banner,
            'left_menu_top': url + 'images/default/left-menu-top.gif', 
            'left_menu_middle': url + 'images/default/left-menu-middle.gif', 
            'left_menu_middle_blank': url + 'images/default/left-menu-middle-blank.gif', 
            'left_menu_bottom': url + 'images/default/left-menu-bottom.gif', 
            'tab_click_isso': url + 'images/default/tab-click-isso.jpg', 
            'tab_noclick_contact': url + 'images/default/tab-noclick-contact.jpg', 
            'tab_noclick_forwarding': url + 'images/default/tab-noclick-forwarding.jpg',
            'grey_square': url + 'images/default/grey-square.gif', 
            'title_isso_home': url + 'images/default/title_isso_home.gif', 
            'dotted-line': url + 'images/default/dotted-line.gif', 
            'white_square': url + 'images/default/white-square.gif', 
            'related_news': url + 'images/' + broker + '/related-news.gif',
            'message': msg,
            'links': sLinks
            }
        self.send_response(200)
        self.writeUserHeader()

        # Get Locale from Request
        locale = self.getHeaderInfo('Accept-Language')
        locale = locale[:2]

        self.writeContentTypeHeader()
        self.end_headers()
        
        #Create page HTML using tenplate
        oTemplate = error(searchList = [contents])
        LogUtil.log(logging.ERROR, 'showIServicesErrorPage():Error page ' 
                     + 'template created')
        page = str(oTemplate)
        #self.wfile.write(page.encode('utf-8'))
		self.wfile.write(page)

    def showIServicesPasswordPage(self, query, sMessage):
        """
        This function displays 'Password Page' to user.
        """
        
        sLocale = query['locale']
        sTitle = self.getProperty('title.login')
        sGreetingLabel = self.getProperty('label.personal.greeting')
        sGreeting = IssoService.getPrincipalMetadata(query['ginu'])
        sMessage = self.getProperty(sMessage)
        pMessage = self.getProperty('label.enter.password')
        pLabel = self.getProperty('label.userpassword')
        rememberLabel = self.getProperty('label.checkbox.remembermachine')
        attempts = "1"
        if 'attempts' in query:
            attempts = query['attempts']
            
        broker = query['broker']
        url = "http://" + broker + "/isso/"
        banner = url + 'images/' + broker + '/ad-banner.gif'
        sLinks = ''
        
        # Prepare data for display
        aData = self.getIBrokerData(broker)
        
        # Get ad-banner
        if not aData == None:
            if not aData[0].startswith('images'):
                banner = aData[0]
        
        # Get static links
        sLinks = self.getStaticLinks(aData, url)
        
        contents = {
            'title': sTitle, 
            'stylesheet': url + 'styleSheets/iservices.css',
            'logo': url + 'images/' + broker + '/ibroker-logo.gif',
            'banner': banner,
            'left_menu_top': url + 'images/default/left-menu-top.gif', 
            'left_menu_middle': url + 'images/default/left-menu-middle.gif', 
            'left_menu_middle_blank': url + 'images/default/left-menu-middle-blank.gif', 
            'left_menu_bottom': url + 'images/default/left-menu-bottom.gif', 
            'tab_click_isso': url + 'images/default/tab-click-isso.jpg', 
            'tab_noclick_contact': url + 'images/default/tab-noclick-contact.jpg', 
            'tab_noclick_forwarding': url + 'images/default/tab-noclick-forwarding.jpg',
            'grey_square': url + 'images/default/grey-square.gif', 
            'title_isso_login': url + 'images/default/title_isso_login.gif',
            'mark_before_greeting': url + 'images/default/mark-before-greeting.jpg', 
            'mark_after_greeting': url + 'images/default/mark-after-greeting.jpg', 
            'dotted_line': url + 'images/default/dotted-line.gif', 
            'button_submit': url + 'images/default/button-submit.jpg', 
            'button_forgot_password': url + 'images/default/button-forgot-password.jpg',
            'forgot_password_url': 'https://' + broker + '/isso/' + 'ForgotPassword', 
            'openid_identity': self.getIname(query['openid.identity']), 
            'openid_return_to': query['openid.return_to'], 
            'openid_mode': query['openid.mode'], 
            'openid_trust_root': query['openid.trust_root'], 
            'openid_assoc_handle': query['openid.assoc_handle'],
            'success_to': query['openid.return_to'], 
            'fail_to': query['openid.return_to'], 
            'ginu': query['ginu'],
            'broker': query['broker'],
            'scookie': '',
            'mcookie': query['mcookie'],
            'locale': query['locale'],
            'attempts': attempts, 
            'white_square': url + 'images/default/white-square.gif', 
            'related_news': url + 'images/' + broker + '/related-news.gif',
            'greeting_label': sGreetingLabel, 
            'greeting': sGreeting, 
            'message': sMessage,
            'pMessage': pMessage,
            'pLabel': pLabel,
            'rememberLabel': rememberLabel, 
            'links': sLinks
            }
        self.send_response(200)
        self.writeUserHeader()
        self.writeContentTypeHeader()
        self.end_headers()

        #Create page HTML using tenplate
        oTemplate = password(searchList = [contents])
        LogUtil.log(logging.ERROR, 'showIServicesErrorPage():Password page ' 
                     + 'template created')
        page = str(oTemplate)
        #self.wfile.write(page.encode('utf-8'))
		self.wfile.write(page)

    def showIServicesRetryPage(self, query):
        """
        This function displays 'Retry Page' to user when machine cookie is not
        valid (user is logging in for the first time from that machine).
        """
        sLocale = query['locale']
        sTitle = self.getProperty('title.unknownMachine')
        sMessage1 = self.getProperty('login.first')
        sMessage2 = self.getProperty('copy.link.for')
        sMessage3 = self.getProperty('copy.link.reasons')
        sMessage4 = self.getProperty('copy.link.reasons.more')
        sMessage5 = self.getProperty('copy.link.1')
        sMessage6 = self.getProperty('copy.link.2')
        sMessage7 = self.getProperty('msg.requesting.provider')
        
        broker = query['broker']
        url = "http://" + broker + "/isso/"
        banner = url + 'images/' + broker + '/ad-banner.gif'
        
        LogUtil.log(logging.INFO, 'showIServicesRetryPage(): entry')
        # Prepare data for display
        aData = self.getIBrokerData(broker)
        
        LogUtil.log(logging.DEBUG, 'showIServicesRetryPage(): Message=Broker Data retrieved')
        # Get ad-banner
        if not aData == None:
            if not aData[0].startswith('images'):
                banner = aData[0]
        
        # Get static links
        sLinks = self.getStaticLinks(aData, url)
        
        contents = {
            'title': sTitle, 
            'stylesheet': url + 'styleSheets/iservices.css',
            'logo': url + 'images/' + broker + '/ibroker-logo.gif',
            'banner': banner,
            'left_menu_top': url + 'images/default/left-menu-top.gif', 
            'left_menu_middle': url + 'images/default/left-menu-middle.gif', 
            'left_menu_middle_blank': url + 'images/default/left-menu-middle-blank.gif', 
            'left_menu_bottom': url + 'images/default/left-menu-bottom.gif', 
            'tab_click_isso': url + 'images/default/tab-click-isso.jpg', 
            'tab_noclick_contact': url + 'images/default/tab-noclick-contact.jpg', 
            'tab_noclick_forwarding': url + 'images/default/tab-noclick-forwarding.jpg',
            'grey_square': url + 'images/default/grey-square.gif', 
            'title_isso_retry': url + 'images/default/title_isso_retry.gif', 
            'dotted_line': url + 'images/default/dotted-line.gif', 
            'button_retry': url + 'images/default/button-retry.jpg', 
            'openid_identity': self.getIname(query['openid.identity']), 
            'openid_return_to': query['openid.return_to'], 
            'openid_mode': query['openid.mode'], 
            'openid_trust_root': query['openid.trust_root'], 
            'openid_assoc_handle': query['openid.assoc_handle'],
            'success_to': query['openid.return_to'], 
            'fail_to': query['openid.return_to'], 
            'ginu': query['ginu'],
            'broker': query['broker'],
            'scookie': query['scookie'],
            'mcookie': query['mcookie'],
            'locale': query['locale'],
            'white_square': url + 'images/default/white-square.gif', 
            'related_news': url + 'images/' + broker + '/related-news.gif', 
            'message1': sMessage1,
            'message2': sMessage2,
            'message3': sMessage3,
            'message4': sMessage4,
            'message5': sMessage5,
            'message6': sMessage6,
            'message7': sMessage7,
            'links': sLinks,
            'url': 'https://' + broker
            }
        self.send_response(200)
        self.writeUserHeader()
        self.writeContentTypeHeader()
        self.end_headers()
        LogUtil.log(logging.INFO, 'showIServicesRetryPage(): Headers written. ' +
                    'Creating template...')
        
        #Create page HTML using tenplate
        oTemplate = retry(searchList = [contents])
        LogUtil.log(logging.DEBUG, 'showIServicesRetryPage(): retry page template created')
        page = str(oTemplate)
        #self.wfile.write(page.encode('utf-8'))
		self.wfile.write(page)

    def verifyTrust(self, query):
        """
        This function checks whether user chose to trust the customer or not.
        If yes, then send "True" response else "False".
        """
        LogUtil.log(logging.DEBUG, 'verifyTrust(): user=' + str(self.user))
        if self.user != '' and self.user != None:
            request = self.server.lastCheckIDRequest.get(self.user)
        else:
            self.user = self.getIname(query['openid.identity'])
            try:
                request = self.server.openid.decodeRequest(query)
            except server.ProtocolError, why:
                self.displayResponse(why)
                return
        
        LogUtil.log(logging.DEBUG, 'verifyTrust(): user=' + str(self.user) +
                    ' ,request=' + str(request))
        
        # Check if session cookie is active or not
        bIsSessionActive = False
        try:
            LogUtil.log(logging.WARN, 'verifyTrust(): Calling resolveIname() '+
                        'for iname=' + str(query['openid.identity']))
            sIdentity = self.getIname(query['openid.identity']) #Normalize
            ginu = self.resolveIname(sIdentity )
            scookie_name = self.getProperty('session.cookie.name')
            scookie = self.getCookie(scookie_name)
            LogUtil.log(logging.WARN,
                        'verifyTrust(): Calling verifySessionState() for ginu='+
                        ginu + ' and Session cookie=' + str(scookie))
            bIsSessionActive = IssoService.verifySessionState(
                ginu, scookie, True)
        except Exception:
            oEx = sys.exc_info()[1]
            LogUtil.log(logging.DEBUG, 'verifyTrust(): Exception=' + str(oEx))
            response = request.answer(False)
            LogUtil.log(logging.DEBUG, 'verifyTrust(): Setting response=' +
                        str(response))
        
        if bIsSessionActive <> True:
            LogUtil.log(logging.DEBUG, 'verifyTrust(): Session is inactive')
            response = request.answer(False)
            LogUtil.log(logging.DEBUG, 'verifyTrust(): Setting response=' +
                        str(response))
        else:
            if 'trust_level' in query:
                if query['trust_level'] == 'yes':
                    LogUtil.log(logging.INFO, 'verifyTrust(): trust=yes')
                    identity = self.getIname(request.identity)
                    trust_root = request.trust_root
                    response = request.answer(True)
                else:
                    LogUtil.log(logging.INFO, 'verifyTrust(): trust=no')
                    response = request.answer(False)
            else:
                LogUtil.log(logging.ERROR, 'verifyTrust(): trust not in query')
                assert False, 'strange allow post.  %r' % (query,)
        
        LogUtil.log(logging.DEBUG,
                    'verifyTrust(): Sending response=' + str(response))
        self.displayResponse(response)
    
    def verifyUser(self, query):
        """
        This function verifies the password provided by the user. If verified,
        show 'Decide Page' otherwise check if user has attempted thrice with
        wrong password, send him back to consumer site without login otherwise
        show 'Password Page'
        """
        LogUtil.log(logging.DEBUG, 'verifyUser(): query=' + str(query))
        if 'cancel' in query:
            self.redirect(query['fail_to'])
            return
        
        try:
            request = self.server.openid.decodeRequest(query)
        except server.ProtocolError, why:
            self.displayResponse(why)
            return

        ginu = None
        broker = None
        scookie = None
        mcookie = None
        locale = "en"
        password = ''
        rememberMachine = True
        
        if 'ginu' in query:
            if query['ginu'] == "null":
                LogUtil.log(logging.ERROR,
                            'verifyUser(): Exception=Invalid global i-number')
                self.showIServicesErrorPage(query, 'Invalid global i-number')
                return
            else:
                ginu = query['ginu']
            
        if 'broker' in query:
            if query['broker'] == "null":
                LogUtil.log(logging.ERROR,
                            'verifyUser(): Exception=Invalid i-broker')
                self.showIServicesErrorPage(query, 'Invalid i-broker')
                return
            else:
                broker = query['broker']
            
        if 'scookie' in query:
            scookie = query['scookie']

        if 'mcookie' in query:
            mcookie = query['mcookie']
            
        if 'locale' in query:
            locale = query['locale']
            
        if 'password' in query:
            password = query['password']
    
        if 'rememberMachine' in query:
            rememberMachine = True
        else:
            rememberMachine = False

        # Check if user is logged in
        sResult = "Failure"
        sMessage = ""
        try:
            LogUtil.log(logging.WARN,
                        'verifyUser(): Calling login()')
            sResult = IssoService.login(ginu, broker, scookie, mcookie,
                                        password, rememberMachine)
        except Exception:
            oEx = sys.exc_info()[1]
            if oEx.getCode() == 1001:
                sResult = "Failure"
                sMessage = "incorrect.password"
                LogUtil.log(logging.ERROR,
                            'verifyUser(): Exception=Password does not match')
        except:
            sResult = "Failure"
            sMessage = "invalid.request.made"
            LogUtil.log(logging.ERROR,
                        'verifyUser(): Exception=Invalid Request')
        
        if sResult == "Success":
            if scookie == None or scookie == '':
                # Create Session Cookie
                LogUtil.log(logging.WARN,
                            'verifyUser(): Calling generateCookie()')
                sSessionCookie = IssoService.generateCookie(ginu)
                LogUtil.log(logging.INFO,
                            'verifyUser(): New scookie=' + str(sSessionCookie))

                # Send Session Cookie to request header
                LogUtil.log(logging.INFO,
                            'verifyUser(): Writing Session Cookie to header')
                query['scookie'] = sSessionCookie

            # Redirect user to Decide Page
            self.user = self.getIname(request.identity)
            LogUtil.log(logging.DEBUG, 'verifyUser(): user=' + str(self.user))
            LogUtil.log(logging.DEBUG,
                        'verifyUser(): lastCheckIDRequest=' +
                        str(self.server.lastCheckIDRequest.get(self.user)))
            LogUtil.log(logging.DEBUG, 'verifyUser(): request=' + str(request))

            if self.server.lastCheckIDRequest.get(self.user) == None:
                self.server.lastCheckIDRequest[self.user] = request
            LogUtil.log(logging.DEBUG,
                        'verifyUser(): Final CheckIDRequest=' +
                        str(self.server.lastCheckIDRequest.get(self.user)))
            self.showIServicesDecidePage(query, request, rememberMachine)
            return
        else:
            # Allow only 3 attempts
            if 'attempts' in query:
                if query['attempts'] == "1":
                    query['attempts'] = "2"
                elif query['attempts'] == "2":
                    query['attempts'] = "3"
                elif query['attempts'] == "3":
                    self.redirect(request.return_to)
                    return
            else:
                query['attempts'] = "1"
            LogUtil.log(logging.DEBUG, 'verifyUser(): sResult <> Success')
            LogUtil.log(logging.DEBUG,
                        'verifyUser(): attempts=' + str(query['attempts']))
            LogUtil.log(logging.DEBUG, 'verifyUser(): Message=' + sMessage)
            self.showIServicesPasswordPage(query, sMessage)
            return

    def writeContentTypeHeader(self):
        """
        This function sends 'Content-Type' header with response.
        """
        self.send_header('Content-Type', 'text/html;charset=UTF-8')

    def writeCookiesHeader(self, cookie_name, cookie_value, expirytime):
        """
        This function sends 'Set-Cookie' header with response.
        """
        path = 'Path=/'
        if cookie_value is None:
            t1970 = time.gmtime(0)
            expires = time.strftime(
                'Expires=%a, %d-%b-%y %H:%M:%S GMT', t1970)
            # Code commented to set secure cookies, now set non-secure cookies
            #header = '%s=;%s;%s;secure;' % (cookie_name, path, expires)
            header = '%s=;%s;%s;' % (cookie_name, path, expires)
            self.send_header('Set-Cookie', header)
        else:
            exptime = time.gmtime(time.time() + expirytime - 1000)
            #1000 less to make cookie old and User agent expires the cookie
            expires = time.strftime(
                'Expires=%a, %d-%b-%y %H:%M:%S GMT', exptime)
            # Code commented to set secure cookies, now set non-secure cookies
            #header = '%s=%s;%s;%s;secure;' % (
            #    cookie_name, cookie_value, path, expires)
            header = '%s=%s;%s;%s;' % (
                cookie_name, cookie_value, path, expires)
            self.send_header('Set-Cookie', header)

    def writeUserHeader(self):
        """
        This function sends 'User' header with response.
        """
        if self.user is None:
            t1970 = time.gmtime(0)
            expires = time.strftime(
                'Expires=%a, %d-%b-%y %H:%M:%S GMT', t1970)
            self.send_header('Set-Cookie', 'user=;%s' % expires)
        else:
            self.send_header('Set-Cookie', 'user=%s' % self.user)

    def handleImmediateMode(self, query):
        """
        This function handles th response for requests with openid.mode=immediate
        """
        
        LogUtil.log(logging.DEBUG, 'handleImmediateMode(): user=' + str(self.user))
        if self.user != '' and self.user != None:
            request = self.server.lastCheckIDRequest.get(self.user)
        else:
            self.user = self.getIname(query['openid.identity'])
            try:
                request = self.server.openid.decodeRequest(query)
            except server.ProtocolError, why:
                self.displayResponse(why)
                return
        
        #create server_url where the non-immediate authentication reuqest
        #can be sent again for completing authentication, in case of first
        #attempt failure
        host = urllib.splitport(self.getHeaderInfo('Host'))
        broker = str(host[0])
        setup_url = "https://" + broker + "/openid/"
        
        LogUtil.log(logging.DEBUG, 'handleImmediateMode(): user=' + str(self.user) + ' ,'
                    + 'request=' + str(request))
        
        # Check if session cookie is active or not
        bIsSessionActive = False
        try:
            LogUtil.log(logging.WARN, 'handleImmediateMode(): Calling resolveIname() '+
                        'for iname=' + str(query['openid.identity']))
            sIdentity = self.getIname(query['openid.identity'])#Normalize XRI
            ginu = self.resolveIname(sIdentity)
            scookie_name = self.getProperty('session.cookie.name')
            
            scookie = self.getCookie(scookie_name)
            LogUtil.log(logging.WARN,
                        'handleImmediateMode(): Calling verifySessionState() for ginu='+
                        ginu + ' and Session cookie=' + str(scookie))
            bIsSessionActive = IssoService.verifySessionState(
                ginu, scookie, True)
        except Exception:
            oEx = sys.exc_info()[1]
            LogUtil.log(logging.DEBUG, 'handleImmediateMode(): Exception=' + str(oEx))
            response = request.answer(False, setup_url)
       
        if bIsSessionActive <> True:
            response = request.answer(False, setup_url)
            LogUtil.log(logging.DEBUG, 'handleImmediateMode(): Session is inactive')
        else:
            response = request.answer(True)
            LogUtil.log(logging.DEBUG, 'handleImmediateMode(): Sending response=True')
        
        LogUtil.log(logging.INFO,
                    'handleImmediateMode(): Sending response=' + str(response))
        self.displayResponse(response)

    """
        Extracts i-name from input text. Input has be a valid XRI or HXRI. HXRI
        domain (xri.*) are read from the iservice properties and are
        configurable. Embedded or naked i-name should start with a GCS
        symbol(=,@,!)
    """
    def getIname(self, sInput):
        LogUtil.log(logging.INFO, 'getIname(): sInput=' + sInput)
        sIname = None
        
        if (sInput.startswith('xri://') == True) and (sInput.startswith('http://')
                                                     == False) and (sInput.startswith('https://')
                                                                   == False):
            LogUtil.log(logging.DEBUG, 'getIname(): Processing XRI=' + sInput)
            sIname = self.__getXri(sInput)
            if sIname <> None:
                LogUtil.log(logging.INFO, 'getIname(): Input is XRI. normalized iname='
                            + sIname )
                return sIname.lower()
        
        #If not an XRI, check for HXRI
        try :
            LogUtil.log(logging.DEBUG, 'getIname(): Processing HXRI')
            tUrl = urlsplit(sInput)
            LogUtil.log(logging.DEBUG, 'getIname(): URL=' + str(tUrl))
            sHxriDomains = str(self.getIserviceProperty('domains.hxri'))
            LogUtil.log(logging.INFO, 'getIname(): HXRI authorities= ' + sHxriDomains)
            
            (sAuthority, port)=urllib.splitnport(str(tUrl[1]))
            LogUtil.log(logging.DEBUG, 'getIname(): HXRI Authoririty= ' + sAuthority)
            if(sHxriDomains.find(sAuthority) <> -1):
                sIname = tUrl[2]
                #Truncate leading slash '\' and escpae as well
                if sIname[:1] == '/':
                    sIname = sIname[1:]
                    
                sIname = self.__getXri(sIname)
                LogUtil.log(logging.INFO, 'getIname(): Returning sInput=' + sInput)
                return sIname.lower()
        except:
            LogUtil.log(logging.WARN, 'getIname(): Invalid HXRI/XRI=' + sInput +
                        ', returning None')
            return None

    
    def __getXri(self, sXri):
        sIname = None;
        
        try:
            if(sXri.startswith('xri://') == True):
                sXri = sXri.strip('xri://')
            
            LogUtil.log(logging.DEBUG, '__getXri(): sXri=' + sXri)
            sIname = self.getauthority(sXri)
            LogUtil.log(logging.DEBUG, '__getXri(): sIname=' + sIname)
            sGCSchars = "=@!"
            if(sGCSchars.find(sIname[:1]) == -1 ):
                return None
            else:
                return sIname.lower()
        except :
            LogUtil.log(logging.WARN, '__getXri(): Returning None. sIname=' + sIname)
            return None

    
    import exceptions

    class MismatchedParentheses(exceptions.SyntaxError):
        pass

    def _findParenMatch(self, fragment, offset=0):
        '''
        Gives the index which is the match for the
        left parentheses at the beginning of the
        sequence parameter
        '''
        level=1 # we start after the first ( which is level 1
        for index in range(offset+1, len(fragment)):
            if fragment[index]=='(':
                level+=1
            if fragment[index]==')':
                level-=1
            if level==0:
                break
        if (index == (len(fragment)-1)) and (fragment[len(fragment)-1] != ")"):
            raise MismatchedParentheses(fragment)
        return index

    def getauthority(self, xri):
        i=0
        while (i< len(xri)):
            if xri[i]=="(":
                i=_findParenMatch(xri, i)
                continue
            if xri[i]=="/":
                break
            i+=1
        return xri[0:i]
    
def main(host, port, data_path):
    # Instantiate OpenID consumer store and OpenID consumer.  If you
    # were connecting to a database, you would create the database
    # connection and instantiate an appropriate store here.
    if port == 80:
        server_url = 'http://%s/openidserver' % host
    else:
        server_url = 'http://%s:%s/openidserver' % (host, port)
    
    # Get DB connection parameters from properties file
    sPath = 'db.properties'    
    oProp = Properties()
    oProp.load(open(sPath))

    conn = MySQLdb.connect (host = oProp['host'],
                           user = oProp['user_name'],
                           passwd = oProp['password'],
                           db = oProp['database'])

    store = MySQLStore(conn)
    
    # Modified for python-openid-1.2
    #oidserver = server.Server(store)
    oidserver = server.OpenIDServer(store)

    addr = (host, port)
    httpserver = OpenIDHTTPServer(oidserver, addr, ServerHandler)

    print 'Server running at:'
    print httpserver.base_url
    httpserver.serve_forever()

if __name__ == '__main__':
    host = 'localhost'
    data_path = 'sstore'
    # port = 8000
    port = 80

    try:
        import optparse
    except ImportError:
        pass # Use defaults (for Python 2.2)
    else:
        parser = optparse.OptionParser('Usage:\n %prog [options]')
        parser.add_option(
            '-d', '--data-path', dest='data_path', default=data_path,
            help='Data directory for storing OpenID consumer state. '
            'Defaults to "%default" in the current directory.')
        parser.add_option(
            '-p', '--port', dest='port', type='int', default=port,
            help='Port on which to listen for HTTP requests. '
            'Defaults to port %default.')
        parser.add_option(
            '-s', '--host', dest='host', default=host,
            help='Host on which to listen for HTTP requests. '
            'Also used for generating URLs. Defaults to %default.')

        options, args = parser.parse_args()
        if args:
            parser.error('Expected no arguments. Got %r' % args)

        host = options.host
        port = options.port
        data_path = options.data_path

    main(host, port, data_path)
